package com.cloud.wms.ui.main.presnter;

import android.content.ComponentName;
import android.content.Intent;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.annimon.stream.Stream;
import com.cloud.core.base.BaseRxPresenter;
import com.cloud.core.http.error.ApiException;
import com.cloud.core.utils.MessageCreator;
import com.cloud.wms.app.FineExApplication;
import com.cloud.wms.config.HttpConfig;
import com.cloud.wms.config.IntentKey;
import com.cloud.wms.config.TaskCode;
import com.cloud.wms.entity.Page;
import com.cloud.wms.http.Params;
import com.cloud.wms.http.observer.LoadingObserver;
import com.cloud.wms.http.observer.ResponseWrapper;
import com.cloud.wms.tools.PageHelper;
import com.cloud.wms.tools.RxUtils;
import com.cloud.wms.tools.TaskHelper;
import com.cloud.wms.ui.data.activity.CheckInventoryActivity;
import com.cloud.wms.ui.data.activity.UploadImgActivity;
import com.cloud.wms.ui.inside.container.ReleaseActivity;
import com.cloud.wms.ui.inside.replenish.ApplyStartActivity;
import com.cloud.wms.ui.inside.revert.RevertCommodityActivity;
import com.cloud.wms.ui.inside.transfer.TransferDownStartActivity;
import com.cloud.wms.ui.inside.transfer.TransferUpStartActivity;
import com.cloud.wms.ui.main.contract.MainContract;
import com.cloud.wms.ui.main.entity.ModelEntity;
import com.cloud.wms.ui.main.entity.RemoteEntity;
import com.cloud.wms.ui.main.entity.TaskEntity;
import com.cloud.wms.ui.main.entity.TaskMemberEntity;
import com.cloud.wms.ui.main.entity.UserEntity;
import com.cloud.wms.ui.print.activity.SelectBoxActivity;
import com.cloud.wms.ui.returned.inquire.FaceSheetStartActivity;
import com.cloud.wms.ui.returned.inventory.ExpressActivity;
import com.cloud.wms.ui.returned.register.ReturnExpressDeliveryActivity;
import com.cloud.wms.ui.returned.relay.RelayBoxActivity;
import com.cloud.wms.ui.sort.car.CarBatchActivity;
import com.cloud.wms.ui.sort.detach.DetachStartActivity;
import com.cloud.wms.ui.sort.entity.BatchInfoEntity;
import com.cloud.wms.ui.sort.order.OrderBatchActivity;
import com.cloud.wms.ui.sort.sku.SkuBatchActivity;

import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.IllegalFormatCodePointException;
import java.util.List;

import javax.inject.Inject;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.functions.Function;

/**
 * @Author:Chen
 * @Date: 2021-01-14 15:51
 * @Description:
 */
public class MainPresenter extends BaseRxPresenter<MainContract.View> implements MainContract.Presenter {
    public static final int TASK_WAIT = 0x101;
    public static final int TASK_WAIT_ERROR = 0x102;
    public static final int TASK_MINE = 0x103;
    public static final int TASK_MINE_ERROR = 0x104;
    public static final int TASK_RECEIVE = 0x105;
    public static final int TASK_REFUSE = 0x106;
    public static final int TASK_EXECUTE = 0x107;

    @Inject
    public MainPresenter() {

    }

    /**
     * 首页模块，跳转页面
     *
     * @param entity
     */
    @Override
    public void matchPath(ModelEntity entity) {
        if (TextUtils.isEmpty(entity.getTaskCode())) {
            jumpTo(entity, false);
            return;
        }

        Params params = Params.newInstance(Params.Type.MEMBER);
        UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
        params.put("JobStationID", userInfo.getJobStationID());
        params.put("ProductCategory", userInfo.getProductCategory());
        params.put("TaskCode", entity.getTaskCode());

        FineExApplication
                .component()
                .http()
                .taskFlowCheck(params)
                .map(new ResponseWrapper<>())
//                .map(taskFlowEntity -> (taskFlowEntity != null && taskFlowEntity.getItems() != null && !taskFlowEntity.getItems().isEmpty()))
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<Boolean>(mView.provideContext()) {
                    @Override
                    public void onSuccess(Boolean aBoolean) {
                        jumpTo(entity, aBoolean);
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    private void jumpTo(ModelEntity entity, boolean isTaskFlow) {
        FineExApplication.component().loginCache().setAppKey(entity.getAppKey());
        try {
            if (TextUtils.isEmpty(entity.getUrl()))
                throw new NullPointerException();
            Intent intent = new Intent();
            String targetPath = "com.cloud.wms.ui." + entity.getUrl();
            ComponentName componentName = new ComponentName(FineExApplication.getInstance().getPackageName(), targetPath);
            intent.setComponent(componentName);
            intent.putExtra(IntentKey.TYPE_KEY, isTaskFlow);
            intent.putExtra(IntentKey.INFO_KEY, entity.getTaskCode());
            mView.provideContext().startActivity(intent);
        } catch (Exception e) {
            Intent intent = new Intent();
            intent.putExtra(IntentKey.TYPE_KEY, isTaskFlow);
            intent.putExtra(IntentKey.INFO_KEY, entity.getTaskCode());
            switch (entity.getModuleName()) {
                case "到货登记":
                    intent.setClass(mView.provideContext(), com.cloud.wms.ui.in.register.InOrderActivity.class);
                    break;
                case "入库清点":
                    intent.setClass(mView.provideContext(), com.cloud.wms.ui.in.inventory.InOrderActivity.class);
                    break;
                case "商品上架":
                    intent.setClass(mView.provideContext(), com.cloud.wms.ui.in.shelf.InOrderActivity.class);
                    break;
                case "箱唛打印":
                    intent.setClass(mView.provideContext(), SelectBoxActivity.class);
                    break;
                case "容器释放":
                    intent.setClass(mView.provideContext(), ReleaseActivity.class);
                    break;
                case "补货申请":
                    intent.setClass(mView.provideContext(), ApplyStartActivity.class);
                    break;
                case "还货":
                    intent.setClass(mView.provideContext(), RevertCommodityActivity.class);
                    break;
                case "团购备货":
                    intent.setClass(mView.provideContext(), com.cloud.wms.ui.sort.group.GroupBatchActivity.class);
                    break;
                case "团购集货":
                    intent.setClass(mView.provideContext(), com.cloud.wms.ui.group.collect.GroupBatchActivity.class);
                    break;
                case "团购领用":
                    intent.setClass(mView.provideContext(), com.cloud.wms.ui.group.obtain.GroupBatchActivity.class);
                    break;
                case "团购抽检":
                    intent.setClass(mView.provideContext(), com.cloud.wms.ui.group.sampling.GroupBatchActivity.class);
                    break;
                case "笼车分拣":
                    intent.setClass(mView.provideContext(), CarBatchActivity.class);
                    break;
                case "订单拣选":
                    intent.setClass(mView.provideContext(), OrderBatchActivity.class);
                    break;
                case "单SKU拣选":
                    intent.setClass(mView.provideContext(), SkuBatchActivity.class);
                    break;
                case "二次分拨":
                    intent.setClass(mView.provideContext(), DetachStartActivity.class);
                    break;
                case "库存查询":
                    intent.setClass(mView.provideContext(), CheckInventoryActivity.class);
                    break;
                case "拍照上传":
                    intent.setClass(mView.provideContext(), UploadImgActivity.class);
                    break;
                case "登记":
                    intent.setClass(mView.provideContext(), ReturnExpressDeliveryActivity.class);
                    break;
                case "清点":
                    intent.setClass(mView.provideContext(), ExpressActivity.class);
                    break;
                case "交接":
                    intent.setClass(mView.provideContext(), RelayBoxActivity.class);
                    break;
                case "移库下架":
                    intent.setClass(mView.provideContext(), TransferDownStartActivity.class);
                    break;
                case "移库上架":
                    intent.setClass(mView.provideContext(), TransferUpStartActivity.class);
                    break;
                case "面单查询":
                    intent.setClass(mView.provideContext(), FaceSheetStartActivity.class);
                    break;
                default:
                    mView.info("当前暂未开放");
                    intent = null;
                    break;
            }
            if (intent != null)
                mView.provideContext().startActivity(intent);
        }
    }

    /**
     * 加载待处理任务
     *
     * @param taskCode
     */
    @Override
    public void loadWaitTask(String taskCode) {
        //1启用 2执行中 3已完成
        Params params = Params.newInstance(Params.Type.MEMBER);
        UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
        params.put("TaskCode", taskCode);
        params.put("JobStationID", userInfo.getJobStationID());
        params.put("ProductCategory", userInfo.getProductCategory());
        params.put("Status", "1");
        if (taskCode.equals(TaskCode.CODE_001001))
            convertTaskList(
                    FineExApplication
                            .component()
                            .http()
                            .waitTaskList(params)
                            .map(new ResponseWrapper<>())
                            .map(RemoteEntity::getItems)
                            .flatMap((Function<ArrayList<TaskEntity>, ObservableSource<TaskEntity>>) Observable::fromIterable)
                            .map(taskEntity -> {
                                taskEntity.setMainBillID(taskEntity.getBillID());
                                taskEntity.setMainBillCode(taskEntity.getBillCode());
                                return taskEntity;
                            })
                            .toList().toObservable(),
                    TASK_WAIT,
                    TASK_WAIT_ERROR
            );
        else
            convertTaskList(
                    FineExApplication
                            .component()
                            .http()
                            .waitTaskList(params, "2")
                            .map(new ResponseWrapper<>())
                            .map(RemoteEntity::getItems)
                            .flatMap((Function<ArrayList<TaskEntity>, ObservableSource<TaskEntity>>) Observable::fromIterable)
                            .map(taskEntity -> {
                                taskEntity.setMainBillID(taskEntity.getBillID());
                                taskEntity.setMainBillCode(taskEntity.getBillCode());
                                return taskEntity;
                            })
                            .toList().toObservable(),
                    TASK_WAIT,
                    TASK_WAIT_ERROR
            );
    }

    /**
     * 加载我的任务
     *
     * @param taskCode
     */
    @Override
    public void loadMineTask(String taskCode) {
        Params params = Params.newInstance(Params.Type.MEMBER);
        UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
        params.put("TaskCode", taskCode);
        params.put("ExecutorID", userInfo.getUserID());
        params.put("Status", "2");

        convertTaskList(
                FineExApplication
                        .component()
                        .http()
                        .mineTaskList(params)
                        .map(new ResponseWrapper<>())
                        .map(RemoteEntity::getItems)
                        .flatMap((Function<ArrayList<TaskEntity>, ObservableSource<TaskEntity>>) Observable::fromIterable)
                        .map(taskEntity -> {
                            if (!taskEntity.isOrderSort()) {
                                taskEntity.setBillID(taskEntity.getMainBillID());
                                taskEntity.setBillCode(taskEntity.getMainBillCode());
                            }
                            return taskEntity;
                        })
                        .toList().toObservable(),
                TASK_MINE,
                TASK_MINE_ERROR
        );
    }

    private void convertTaskList(Observable<List<TaskEntity>> observable, int messageCode, int errorMessageCode) {
        observable
                .map(remoteTaskEntities -> {
                    ArrayList<TaskMemberEntity> taskMemberList = new ArrayList<>();
                    Stream.ofNullable(remoteTaskEntities)
                            .groupBy(TaskEntity::getMemberID)
                            .forEach(entry -> {
                                TaskMemberEntity memberEntity = new TaskMemberEntity();
                                memberEntity.setMemberID(entry.getKey());
                                memberEntity.setExpanded(taskMemberList.isEmpty());

                                List<TaskEntity> taskList = new ArrayList<>();
                                Stream.ofNullable(entry.getValue())
                                        .forEach(remoteTaskEntity -> {
                                            memberEntity.setMemberName(remoteTaskEntity.getMemberName() + "");
                                            remoteTaskEntity.setExecutorID(FineExApplication.component().loginCache().getUserInfo().getUserID());
                                            taskList.add(remoteTaskEntity);
                                        });
                                memberEntity.setChildNode(taskList);

                                taskMemberList.add(memberEntity);
                            });
                    return taskMemberList;
                })
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<ArrayList<TaskMemberEntity>>(mView.provideContext()) {
                    @Override
                    public void onSuccess(ArrayList<TaskMemberEntity> info) {
                        mView.onSuccess(MessageCreator.createMessage(info, messageCode));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                        mView.onSuccess(MessageCreator.createMessage(null, errorMessageCode));
                    }
                });
    }

    @Override
    public void searchTask(String taskCode, String searchKey, boolean isWaitTask) {
        Params params = Params.newInstance(Params.Type.MEMBER);
        params.put("BatchCode", searchKey);
        FineExApplication
                .component()
                .http()
                .getBatchIdByCode(params)
                .map(new ResponseWrapper<>())
                .flatMap((Function<String, ObservableSource<String>>) batchId -> {
                    if (TextUtils.isEmpty(batchId)) {
                        return Observable.error(new ApiException("未查询对应业务数据信息！"));
                    }
                    return Observable.just(batchId);
                })
                .flatMap((Function<String, ObservableSource<RemoteEntity<TaskEntity>>>) batchId -> {
                    Params paramsTask = Params.newInstance(Params.Type.MEMBER);
                    UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
                    paramsTask.put("TaskCode", taskCode);
                    paramsTask.put("BillID", batchId);

                    if (!isWaitTask) {
                        paramsTask.put("Status", "2");
                        paramsTask.put("ExecutorID", userInfo.getUserID());
                        return FineExApplication
                                .component()
                                .http()
                                .mineTaskList(paramsTask)
                                .map(new ResponseWrapper<>());
                    } else {
                        paramsTask.put("Status", "1");
                        paramsTask.put("JobStationID", userInfo.getJobStationID());
                        paramsTask.put("ProductCategory", userInfo.getProductCategory());
                        return FineExApplication
                                .component()
                                .http()
                                .waitTaskList(paramsTask, "2")
                                .map(new ResponseWrapper<>());
                    }
                })
                .flatMap((Function<RemoteEntity<TaskEntity>, ObservableSource<ArrayList<TaskEntity>>>) remoteEntity -> {
                    if (remoteEntity == null || remoteEntity.getItems() == null || remoteEntity.getItems().isEmpty()) {
                        return Observable.error(new ApiException("未查询当前波次对应的任务！"));
                    }
                    return Observable.just(remoteEntity.getItems());
                })
                .flatMap((Function<ArrayList<TaskEntity>, ObservableSource<TaskEntity>>) Observable::fromIterable)
                .map(taskEntity -> {
                    // 订单拣选
                    if (taskEntity.isOrderSort()) {
                        if (isWaitTask) {
                            taskEntity.setMainBillID(taskEntity.getBillID());
                            taskEntity.setMainBillCode(taskEntity.getBillCode());
                        }
                    } else {
                        if (isWaitTask) {
                            taskEntity.setMainBillID(taskEntity.getBillID());
                            taskEntity.setMainBillCode(taskEntity.getBillCode());
                        } else {
                            taskEntity.setBillID(taskEntity.getMainBillID());
                            taskEntity.setBillCode(taskEntity.getMainBillCode());
                        }
                    }
                    return taskEntity;
                })
                .toList().toObservable()
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<List<TaskEntity>>(mView.provideContext()) {
                    @Override
                    public void onSuccess(List<TaskEntity> info) {
                        if (info == null || info.isEmpty()) {
                            mView.info("未查询到相关数据！");
                            return;
                        }
                        mView.onSuccess(MessageCreator.createMessage(info, PageHelper.LIST_NEW_DATA));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    /**
     * 领取任务
     *
     * @param taskEntity
     * @param isExecute
     */
    @Override
    public void receiveTask(TaskEntity taskEntity, boolean isExecute) {
        Params params = new Params();
        params.put("TaskID", taskEntity.getTaskID());
        UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
        params.put("JobStationID", userInfo.getJobStationID());
        params.put("ProductCategory", userInfo.getProductCategory());
        params.put("ExecutorID", userInfo.getUserID());
        TaskHelper.receiveTask(params)
                .map(workId -> {
                    taskEntity.setWorkID(workId);
                    return taskEntity;
                })
                .flatMap((Function<TaskEntity, ObservableSource<TaskEntity>>) task -> {
                    if (TaskCode.CODE_009001.equalsIgnoreCase(task.getTaskCode())) {
                        Params paramsReplenish = new Params();
                        paramsReplenish.put("BillID", task.getBillID());
                        return FineExApplication
                                .component()
                                .http()
                                .loadReplenishOrderStatus(paramsReplenish)
                                .map(new ResponseWrapper<>())
                                .map(aVoid -> task);
                    } else {
                        return Observable.just(task);
                    }
                })
                .map(aVoid -> taskEntity)
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<TaskEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(TaskEntity info) {
                        if (isExecute) {
                            mView.onSuccess(MessageCreator.createMessage(info, TASK_EXECUTE));
                        } else
                            mView.onSuccess(MessageCreator.createMessage(info, TASK_RECEIVE));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    /**
     * 领取任务
     *
     * @param task
     * @param isExecute
     */
    @Override
    public void receiveOrderTask(TaskEntity task, boolean isExecute) {
        Params paramsReceived = Params.newInstance(Params.Type.MEMBER);
        paramsReceived.put("BillID", task.getBillID());
        paramsReceived.put("TaskCode", task.getTaskCode());
        FineExApplication
                .component()
                .http()
                .sortReceivedOrderId(paramsReceived)
                .map(new ResponseWrapper<>())
                .flatMap((Function<ArrayList<TaskEntity>, ObservableSource<Long>>) tasks -> {
                    IdentityHashMap<String, Object> paramsNoReceive = new IdentityHashMap<>();
                    paramsNoReceive.put("BatchID", task.getBillID());
                    ArrayList<Long> orderIds = new ArrayList<>();
                    if (tasks != null && !tasks.isEmpty()) {
                        for (int i = 0; i < tasks.size(); i++) {
                            orderIds.add(tasks.get(i).getBillID());
                        }
                    }
                    paramsNoReceive.put("lisOrderID", orderIds);
                    return FineExApplication
                            .component()
                            .http()
                            .sortNoReceiveOrderId(paramsNoReceive)
                            .map(new ResponseWrapper<>())
                            .flatMap((Function<ArrayList<Long>, ObservableSource<Long>>) longs1 -> {
                                if (longs1 == null || longs1.isEmpty()) {
                                    return Observable.error(new ApiException("当前波次没有可执行的订单！"));
                                }
                                return Observable.just(longs1.get(0));
                            });
                })
                .flatMap((Function<Long, ObservableSource<TaskEntity>>) aLong -> {
                    Params params = new Params();
                    params.put("TaskID", task.getTaskID());
                    UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
                    params.put("JobStationID", userInfo.getJobStationID());
                    params.put("ProductCategory", userInfo.getProductCategory());
                    params.put("ExecutorID", userInfo.getUserID());
                    return TaskHelper.receiveTask(params)
                            .map(aVoid -> {
                                task.setMainWorkID(aVoid);
                                task.setMainBillID(task.getBillID());
                                task.setMainBillCode(task.getBillCode());
                                task.setBillID(aLong);
                                return task;
                            });
                })
                .flatMap((Function<TaskEntity, ObservableSource<TaskEntity>>) taskEntity -> {
                    Params params = new Params();
                    params.put("TaskID", taskEntity.getTaskID());
                    params.put("OrderID", taskEntity.getBillID());
                    UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
                    params.put("JobStationID", userInfo.getJobStationID());
                    params.put("ProductCategory", userInfo.getProductCategory());
                    params.put("ExecutorID", userInfo.getUserID());
                    return TaskHelper.receiveOrderTask(params)
                            .map(aVoid -> {
                                taskEntity.setWorkID(aVoid);
                                return taskEntity;
                            });
                })
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<TaskEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(TaskEntity info) {
                        if (isExecute)
                            mView.onSuccess(MessageCreator.createMessage(info, TASK_EXECUTE));
                        else
                            mView.onSuccess(MessageCreator.createMessage(info, TASK_RECEIVE));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    /**
     * 拒绝任务
     *
     * @param taskEntity
     */
    @Override
    public void refuseTask(TaskEntity taskEntity) {
        TaskHelper.refuseTask(taskEntity.getWorkID() + "")
                .map(aVoid -> taskEntity)
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<TaskEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(TaskEntity info) {
                        mView.onSuccess(MessageCreator.createMessage(info, TASK_REFUSE));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    /**
     * 执行任务
     *
     * @param taskEntity
     */
    @Override
    public void executeTask(TaskEntity taskEntity) {
        Params params = new Params();
        params.put("workId", taskEntity.getWorkID());
        params.put("executerId", taskEntity.getExecutorID());
        TaskHelper.executeTask(params)
                .map(aVoid -> taskEntity)
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<TaskEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(TaskEntity info) {
                        mView.onSuccess(MessageCreator.createMessage(info, TASK_EXECUTE));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }

    /**
     * 执行任务
     *
     * @param taskEntity
     */
    @Override
    public void executeOrderTask(TaskEntity taskEntity) {
        Params params = new Params();
        params.put("TaskCode", taskEntity.getTaskCode());
        params.put("BatchID", taskEntity.getMainBillID());
        UserEntity userInfo = FineExApplication.component().loginCache().getUserInfo();
        params.put("JobStationID", userInfo.getJobStationID());
        params.put("ExecutorID", userInfo.getUserID());
        FineExApplication
                .component()
                .http()
                .userOrderTask(params)
                .map(new ResponseWrapper<>())
                .flatMap((Function<TaskEntity, ObservableSource<TaskEntity>>) task -> {
                    Params params1 = new Params();
                    params1.put("workId", task.getWorkID());
                    params1.put("executerId", task.getExecutorID());
                    return TaskHelper.executeTask(params1)
                            .map(aVoid -> {
                                task.setMainWorkID(taskEntity.getWorkID());
                                return task;
                            });
                })
                .compose(mView.toLifecycle())
                .compose(RxUtils.threadSwitch())
                .subscribe(new LoadingObserver<TaskEntity>(mView.provideContext()) {
                    @Override
                    public void onSuccess(TaskEntity info) {
                        mView.onSuccess(MessageCreator.createMessage(info, TASK_EXECUTE));
                    }

                    @Override
                    public void onError(String msg) {
                        mView.error(msg);
                    }
                });
    }
}
